package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)

type ABstore struct {
	contractapi.Contract
}

// init
func (t *ABstore) init(ctx contractapi.TransactionContextInterface, A string, Aval int, B string, Bval int) error {
	exist, err := ctx.GetStub().GetState(A)
	if err != nil {
		return errors.New("fail to get state")
	}
	if exist != nil {
		return errors.New("the state is already exist")
	}
	Avalstring := strconv.Itoa(Aval)
	err = ctx.GetStub().PutState(A, []byte(Avalstring))
	if err != nil {
		return errors.New("unable to put A to state")
	}
	Bvalstring := strconv.Itoa(Bval)
	err = ctx.GetStub().PutState(B, []byte(Bvalstring))
	if err != nil {
		return errors.New("unable to put B to state")
	}
	return nil
}

//invoke transaction makes payment of x tokens from A to B
func (t *ABstore) invoke(ctx contractapi.TransactionContextInterface, A, B string, x int) error {
	Avalbytes, err := ctx.GetStub().GetState(A)
	if err != nil {
		return errors.New("failed to get state ")
	}
	if Avalbytes == nil {
		return errors.New("empty")
	}
	Aval, _ := strconv.Atoi(string(Avalbytes))
	Bvalbytes, err := ctx.GetStub().GetState(B)
	if err != nil {
		return errors.New("failed to get state ")
	}
	if Bvalbytes == nil {
		return errors.New("empty")
	}
	Bval, _ := strconv.Atoi(string(Bvalbytes))
	if Aval-x < 0 {
		return errors.New("there is not enough tokens")
	}
	Aval = Aval - x
	Bval = Bval + x
	err = ctx.GetStub().PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return err
	}
	err = ctx.GetStub().PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return err
	}
	return nil
}

// delete
func (t *ABstore) delete(ctx contractapi.TransactionContextInterface, A string) error {

	err := ctx.GetStub().DelState(A)
	if err != nil {
		fmt.Println("failed to delete state")
		return err
	}
	return nil
}

//query
func (t *ABstore) query(ctx contractapi.TransactionContextInterface, A string) (string, error) {
	Avalbyte, err := ctx.GetStub().GetState(A)
	if err != nil {
		return "", err
	}
	if Avalbyte == nil {
		return "", errors.New("the state is empty")
	}
	res := "query result: " + string(Avalbyte)
	return res, nil
}

func main() {
	cc, err := contractapi.NewChaincode(new(ABstore))
	if err != nil {
		panic(err.Error())
	}
	if err := cc.Start(); err != nil {

		fmt.Printf("error acurred: %s", err.Error())
	}
}
